package net.peelmeagrape.hibernate;

import net.peelmeagrape.hibernate.xmlgen.XmlAttribute;
import net.peelmeagrape.hibernate.xmlgen.XmlElement;
import net.peelmeagrape.hibernate.xmlgen.AddPropertyNameAsAttribute;

import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.ElementType.METHOD;
import java.lang.annotation.Retention;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import java.lang.annotation.Target;

/**
 * A one-to-one association to another persistent class.
 * There are two varieties of one-to-one association:
 * <ul>
 * <li>primary key associations</li>
 * <li>unique foreign key associations</li>
 * </ul>
 * Primary key associations don't need an extra table column; if two rows are related by
 * the association then the two table rows share the same primary key value. So if you want
 * two objects to be related by a primary key association, you must make sure that they
 * are assigned the same identifier value!
 * <br/>
 * See <a href="{@docRoot}/reference/en/html/mapping.html#mapping-declaration-onetoone">Hibernate Documentation for &lt;one-to-one&gt;</a>
 * for more information
 */
@Target({METHOD,FIELD}) @Retention(RUNTIME)
@XmlElement(name="one-to-one")
@AddPropertyNameAsAttribute(name="name")
public @interface OneToOne
{
    /**
     * Almost all one to one associations map to the primary key of the owning entity. In the rare case that this is
     * not the case, you may specify a some other column, columns or expression to join on using an SQL formula.
     * (See org.hibernate.test.onetooneformula for an example.)
     */
    @XmlAttribute String formula() default "";
    /**
     * The strategy Hibernate should use for accessing the property value. This may be one of
     * 'property', 'field', 'embedded', or the name of a subclass of {@link org.hibernate.property.PropertyAccessor}.
     */
    @XmlAttribute String access() default "property";

    /**
     * (optional - defaults to the property type determined by reflection): The name of the associated class.
     */
    @XmlAttribute("class") Class[] targetClass() default {};

    /**
     * The entity name of the associated class.
     */
    @XmlAttribute("entity-name") String entityName() default "";

    /**
     * Specifies which operations should be cascaded from this object to the associated object.
     */
    @XmlAttribute String cascade() default "";
    @XmlAttribute OuterJoinSetting outerJoin() default OuterJoinSetting.AUTO;

    /**
     * Chooses between outer-join fetching or sequential select fetching.
     */
    @XmlAttribute FetchSetting fetch() default FetchSetting.SELECT;

    /**
     * Specifies that a foreign key constraint on the primary key of the mapped table references the table
     * of the associated class. This option affects the order in which save() and delete() are cascaded,
     * and determines whether the association may be proxied (it is also used by the schema export tool).
     */
    @XmlAttribute boolean constrained() default false;
    @XmlAttribute("foreign-key") String foreignKey() default "";

    /**
     * The name of a property of the associated class that is joined to the primary key of this class.
     * If not specified, the primary key of the associated class is used.
     */
    @XmlAttribute("property-ref") String propertyRef() default "";

    /**
     * By default, single point associations are proxied. <tt class="literal">lazy="true"</tt>
     * specifies that the property should be fetched lazily when the instance variable
     * is first accessed (requires build-time bytecode instrumentation).
     * <tt class="literal">lazy="false"</tt> specifies that the association will always
     * be eagerly fetched. <span class="emphasis"><em>Note that if <tt class="literal">constrained="false"</tt>,
     * proxying is impossible and Hibernate will eager fetch the association!</em>
     */
    @XmlAttribute LazySetting[] lazy() default {};
    @XmlAttribute String node() default "";
    @XmlAttribute("embed-xml") boolean embedXml() default true;

    Meta[] meta() default {};
}
